from django.db.models import Q, Sum
from django.shortcuts import render
# Create your views here.
from django.utils import timezone
from rest_framework.decorators import action
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ModelViewSet, GenericViewSet, ViewSet
from rest_framework.mixins import ListModelMixin, UpdateModelMixin, RetrieveModelMixin

from students.models import Class, Student
from django.db.models import Count
from .serializers import *

#教学周期视图
class TeachingTimeView(ModelViewSet):
    queryset = TeachingTime.objects.all()
    serializer_class = TeachingTimeSerializer
    def getTeachingTime(self,request):
        queryinfo = request.query_params.get('queryinfo')
        if (queryinfo == 'current'):
            instance=get_object_or_404(TeachingTime,is_start=True)
            ser=self.get_serializer(instance)
            return Response(ser.data)
        self.pagination_class = None
        if (queryinfo == 'activated'):
            self.queryset = TeachingTime.objects.filter(endtime__gt=timezone.now())
        return self.list(request)

    def getTeachingCycleDateTime(self,request):
        id=request.query_params.get("id")
        res=TeachingTime.objects.filter(id=id).values("starttime",'endtime')[0]
        data={
            "starttime":res["starttime"],
            "endtime":res["endtime"]
        }
        return Response(data)
#学院课程阶段视图
class CollegeStageView(ModelViewSet):
    queryset = CollegeStage.objects.all()
    serializer_class = CollegeStageSerializer
    filter_fields = ('college_id',)
    def get_queryset(self):
        queryinfo=self.request.query_params.get('queryinfo')
        if(queryinfo=='nopaging'):
            self.pagination_class=None
        return self.queryset

#课程体系视图
class CoursesView(ModelViewSet):
    queryset = Courses.objects.all()
    serializer_class = CoursesSerializer
    filter_fields = ('school_id',)
    def list(self, request, *args, **kwargs):
        cls_id = request.query_params.get('class_id')
        if (cls_id):
            self.pagination_class = None  # 不分页
            try:
                cls = Class.objects.get(pk=cls_id)
                self.queryset = cls.school.courses_set.all()
            except:
                self.queryset = []
        return super(CoursesView, self).list(request)
# 排课视图
class CoursePlanView(ModelViewSet):
    queryset = CoursePlan.objects.all()
    serializer_class = CoursePlanSerializer
    def list(self, request, *args, **kwargs):
        cls_id = request.query_params.get('cls_id')
        tc_id = request.query_params.get('tc_id')
        if (cls_id and tc_id):
            self.pagination_class = None
            try:
                instance = CoursePlan.objects.get(cls_id=cls_id, teaching_time_id=tc_id)
            except:
                instance = CoursePlan()
            serializer = self.get_serializer(instance)
            return Response(serializer.data)
        return super(CoursePlanView, self).list(request)
    # 教务排课表
    def getCourseTable(self, request):
        page = int(request.query_params.get('page', 1))
        page_size = int(request.query_params.get('page_size', 5))
        if page_size > 20:
            page_size = 20
        tc_id = request.query_params.get('tc_id')
        college_id = request.query_params.get('college_id')
        stage_id = request.query_params.get('stage_id')
        if tc_id and college_id and stage_id is None:
            queryset = CoursePlan.objects.all().values('teaching_time__title', 'lecturer__name', 'counsellor__name',
                                                       'cls_id__name', 'class_time', 'course__name', "course_id"
                                                                                                     'course__stage',
                                                       'course_id__school_id__name')
            start = (page - 1) * page_size
            data = {'count': queryset.count(), 'data': list(queryset[start:page * page_size])}
            return Response(data)
        else:
            where = Q()
            if tc_id:
                where.add(Q(teaching_time_id=tc_id), Q.AND)
            if college_id:
                where.add(Q(course__college_stage__college_id=college_id), Q.AND)
                if stage_id:
                    where.add(Q(course__college_stage_id=stage_id), Q.AND)

            queryset = CoursePlan.objects.filter(where).values('teaching_time__title', 'lecturer__name',
                                                               'counsellor__name', 'cls_id__name', 'class_time',
                                                               'course__name', 'course__stage',
                                                               'course_id__school_id__name', "course_id")
            print(queryset)
            start = (page - 1) * page_size
            data = {'count': queryset.count(), 'data': list(queryset[start:page * page_size])}
            return Response(data)




        # return super(CoursePlanView,self).list(request)






#用户所带班级 及 调课、代课
class UserCoursePlanView(ViewSet):
    # 获取用户本月教学周期的排课信息
    def getUserCoursePlan(self, userId):
        try:
            #获取的是最新发布的教学周期
            tc = TeachingTime.objects.get(is_start=True)
            cp = CoursePlan.objects.filter(teaching_time_id=tc.id, lecturer_id=userId)
            return cp
        except:
            return None
    #获取用户的排课(排班)记录
    def getCoursePlan(self, request):
        cp = self.getUserCoursePlan(request.user.id)
        if cp:
            ser = UserCoursePlanSerializer(cp, many=True)
            return Response(ser.data)
        return Response([])
    #验证用户的调课记录
    def validate(self, data, id):
        error_message = {}
        if not data.get('course_plan_id'):
            error_message['course_plan_id'] = '排课id course_plan_id 参数必须'
        change_type = data.get('change_type')
        if change_type is None:
            error_message['change_type'] = '调课类型change_type 参数是必须的'
        if not data.get('original_date'):
            error_message['original_date'] = '原上课日期 original_date 参数是必须的'

        original_class = data.get('original_class', [])
        if not original_class:
            error_message['original_class'] = '原课节 original_class 参数是必须的'

        if not data.get('change_date'):
            error_message['change_date'] = '调课日期 change_date 参数是必须的'

        from datetime import datetime
        changeTime = datetime.strptime(data['change_date'], '%Y-%m-%d')
        nowTimeStr = timezone.now().strftime("%Y-%m-%d")
        nowTime = datetime.strptime(nowTimeStr, '%Y-%m-%d')
        if changeTime < nowTime:
            error_message['change_date'] = '调课日期 change_date 不能是之前的日期'
        change_class = data.get('change_class', [])
        if not change_class:
            error_message['change_class'] = '调整后的课节 change_class 参数是必须的'
        if change_class and (len(original_class) != len(change_class)):
            error_message['change_class'] = '课节数不匹配'
        data['teacher_id'] = id
        # 调课
        if change_type == 0:
            data['change_teacher'] = id
        else:
            # 代课
            if not data.get('change_teacher'):
                error_message['change_teacher'] = '代课老师 change_teacher 不能为空'
            else:
                data['change_teacher'] = data.get('change_teacher')
        if (error_message):
            return {'errors': error_message}

        return data
    #调课与代课
    def adjustClassSection(self, request):
        data = self.validate(request.data, request.user.id)  # 获取请求参数 对数据进行验证
        if data.get('errors'):
            return Response(data, status=400)

        # 根据排课id 获取 本班的正课时间
        try:
            cp = CoursePlan.objects.get(pk=data['course_plan_id'])
            data['cls_id']=cp.cls_id
            classTime = cp.class_time.split(',')  # 列表中的元素是字符串
            # 验证接收到的 原课节 是不是正课
            for i in data['original_class']:
                if str(i) not in classTime:
                    return {'errors': '原课节只能是' + cp.class_time}
        except:
            return {'errors': 'course_plan_id 参数错误 找不到对应的排课信息'}

        # 获取代课讲师正常的正课时间
        cp = self.getUserCoursePlan(data['change_teacher'])
        userClassTime = []
        if cp:
            for c in cp:
                userClassTime.extend(c.class_time.split(','))

        print("*"*50)
        print('用户正常的正课时间:',userClassTime)# 2 3 5 6

        # 获取代课讲师 change_date 这一天实际的正课时间
        result = AdjustClassTime.objects.filter(teacher_id=data['change_teacher'], original_date=data['change_date'])
        for i in result:
            ajc = i.adjustclassmap_set.filter(is_take_effect=True)
            for a in ajc:
                if a.initial==a.final and i.original_date==i.change_date:
                    continue
                cl=a.initial.split('-')[-1]
                if cl in userClassTime:
                    userClassTime.remove(a.initial.split('-')[-1])
        print('用户实际的正课时间:', userClassTime)
        #获取代课讲师 调代课之后的 正课时间
        result = AdjustClassTime.objects.filter(change_teacher_id=data['change_teacher'],change_date=data['change_date'])
        classMap = {}
        for i in result:
            ajc = i.adjustclassmap_set.filter(is_take_effect=True)
            for a in ajc:
                classMap[a.initial] = a.final
        classMapList=list(map(lambda x:x.split('-')[-1],list(classMap.values())))
        print('用户调整后的正课时间:', classMapList)
        userClassTime.extend(classMapList)
        print('用户当天的正课时间:', userClassTime)

        occupyClass=list(set(userClassTime) & set(list(map(str,data['change_class']))))
        if occupyClass:
            return Response({'errors': f"{data['change_date']}第{str(occupyClass)}节课已经被占用了~"})
        result=AdjustClassTime.objects.create(course_plan_id=data['course_plan_id'],original_date=data['original_date'],change_date=data['change_date'],change_type=data['change_type'],change_teacher_id=data['change_teacher'],teacher_id=data['teacher_id'],cls_id=data['cls_id'])
        for index,item in enumerate(data['change_class']):
            initial=f'{result.original_date}-{data["original_class"][index]}'
            AdjustClassMap.objects.filter(act__teacher_id=data['teacher_id'],initial=initial).update(is_take_effect=False)
            AdjustClassMap.objects.create(act=result,final=f'{result.change_date}-{item}',initial=initial)
        return Response({})

#用户的调课信息视图(调课审核)
class AdjustClassTimeView(GenericViewSet,ListModelMixin,UpdateModelMixin):
    queryset = AdjustClassTime.objects.all()
    serializer_class = AdjustClassTimeSerializer

    def list(self, request, *args, **kwargs):
        id = request.user.id
        data = list(AdminUser.objects.filter(id=id).values('role__level', 'role__duty'))[0]
        role = ''
        if data['role__level'] == 3 and data['role__duty'] == 2:
            role = 'teacher'
        elif data['role__level'] == 1 and data['role__duty'] == 1:
            role = 'headMaster'
        elif data['role__duty'] == 0:
            role = 'education'
        if role == 'teacher':
            self.queryset = AdjustClassTime.objects.filter(teacher_id=request.user.id)
        elif role == 'headMaster':
            collegeId = AdminUser.objects.filter(id=request.user.id).values('role__department_id')[0][
                'role__department_id']
            self.queryset = AdjustClassTime.objects.filter(cls__school_id=collegeId, state__lt=3)
        elif role == 'education':
            college = request.query_params.get('college')
            where = Q(state=1)
            if college:
                print(college)
                where.add(Q(cls__school_id=college), Q.AND)
            self.queryset = AdjustClassTime.objects.filter(where)
        return super(AdjustClassTimeView, self).list(request)

    def update(self, request, *args, **kwargs):
        state=request.data.get('state')
        id=self.kwargs.get('pk')
        #审核不通过
        if state==-1:
            AdjustClassMap.objects.filter(act_id=id).update(is_take_effect=False)
        else:
            #调课的课节映射记录
            acm=AdjustClassMap.objects.filter(act_id=id)
            for i in acm:
                #获取调课记录的 原课节日期 和 原课节
                date,section=i.initial.rsplit('-',maxsplit=1)
                # 获取调课记录的 新课节日期 和 新课节
                actual_date,actual_section=i.final.rsplit('-',maxsplit=1)
                RollCall.objects.filter(teaching_time_id=i.act.course_plan.teaching_time_id,class_date=date,class_section=section,lecturer=i.act.teacher.name).update(actual_date=actual_date,actual_section=actual_section,lecturer=i.act.change_teacher.name,act_id=id,lecturer_id=i.act.change_teacher_id)
        return super(AdjustClassTimeView, self).update(request,partial=True)

    @action(methods=['get'],detail=False)
    def UpdateState(self,request):
        id=request.query_params.get('id')
        data=AdjustClassTime.objects.filter(id=id).update(state=3)
        return Response(data)

#讲师的课表视图
class RollCallView(ModelViewSet):
    serializer_class = RollCallSerializer
    queryset = RollCall.objects.all()
    #根据教学周期id和学院id 获取每个讲师带了多少节课
    def getClassSections(self,request):
        # 获取当前的教学周期id
        tc = self.request.query_params.get('tc_id')
        #获取学院id
        college=self.request.query_params.get('college_id')
        # 根据教学周期id 获取已经点名课表
        result=RollCall.objects.filter(teaching_time_id=tc, state=True,college_id=college).values('lecturer_id').annotate(section_num=Count('id')).values('section_num','lecturer','college__name','teaching_time__title','lecturer_id','teaching_time_id')
        return Response(list(result))
    #获取某一个老师 带课程对应的的课节
    def getClassInfo(self,request):
        lecturer_id=self.request.query_params.get('lecturer_id')
        tc = self.request.query_params.get('tc_id')
        result = RollCall.objects.filter(teaching_time_id=tc, state=True, lecturer_id=lecturer_id).values(
            'class_id').annotate(section_num=Count('id')).values('section_num', 'lecturer','class_name','college__name','course')
        return Response(list(result))
    def retrieve(self, request, *args, **kwargs):
        instance=self.get_object()#获取单个课表对象
        data={'state':0,'students':[]}
        #查询班级的学生信息
        if instance.state == 0:
            #没有点名
            classObj=Class.objects.get(name=instance.class_name,school_id=instance.college_id)
            students=Student.objects.filter(cls=classObj).values('name','idcardnumber')
            data['students']=list(students)
        else:
            normal=instance.normal.split(',') if instance.normal else []
            cut_classes=instance.cut_classes.split(',') if instance.cut_classes else []
            leave=instance.leave.split(',') if instance.leave else []
            late=instance.late.split(',') if instance.late else []

            idcardnumber=normal+cut_classes+leave+late
            students=Student.objects.filter(idcardnumber__in=idcardnumber).values('name','idcardnumber')
            for s in students:
                #出勤：1 旷课：2 请假：3 迟到：4
                s['state'] = 1 # 学生的出勤状态
                if s['idcardnumber'] in cut_classes:
                    s['state']=2
                if s['idcardnumber'] in leave:
                    s['state']=3
                if s['idcardnumber'] in late:
                    s['state']=4
                data['students'].append(s)
                data['state']=1#该课表是否已经被点名
        return Response(data)
    def update(self, request, *args, **kwargs):
        return super(RollCallView, self).update(request,partial=True)
    #根据讲师 获取讲师的点名表
    def getPointNameTable(self,request):
        self.queryset=RollCall.objects.filter(lecturer=self.request.user.name, class_date__lte=timezone.now()).order_by('state','-actual_date','actual_section')
        return self.list(request)
    #获取出勤率的方法
    def getAttendance(self,request):
        page=request.query_params.get('page',1)
        page_size=request.query_params.get('page_size',5)
        if page_size>20:
            page_size=20
        show_type = request.query_params.get('show_type')  # 展示类型
        date=request.query_params.get('date',timezone.now().strftime('%Y-%m-%d'))#日期
        start=request.query_params.get('start')#开始时间
        end=request.query_params.get('end')#结束时间
        tc_id=request.query_params.get('tc_id')#教学周期
        type=request.query_params.get('type')# 类型：学院、班级、阶段
        type_field={'class':'class_id','stage':'college_stage_id','college':'college_id'}
        group_field=type_field.get(type,'class_id')
        college_id = request.query_params.get('college_id')

        where=Q(state=True)
        if college_id:
            where.add(Q(college_id=college_id),Q.AND)
        #判断展示类型
        if show_type=='1':
            where.add(Q(actual_date=date),Q.AND)
        elif show_type=='2':
            where.add(Q(actual_date__range=(start,end)),Q.AND)
        elif show_type=='3':
            where.add(Q(teaching_time_id=tc_id),Q.AND)

        queryset = RollCall.objects.filter(where).values(group_field).annotate(
            total_studends_num=Sum('students_num'), total_attendance_num=Sum('attendance_num'))

        # queryset = RollCall.objects.filter(where).values('college_id').annotate(total_studends_num=Sum('students_num'),total_attendance_num=Sum('attendance_num')).values('class_name', 'total_studends_num', 'total_attendance_num','college__name')
        # print(queryset)
        # return  Response({})


        if group_field=='class_id':
            result=queryset.values('class_name', 'total_studends_num', 'total_attendance_num','teaching_time__title','college__name')
        elif group_field=='college_stage_id':
            result=queryset.values('college_stage__name','college__name','teaching_time__title', 'total_studends_num', 'total_attendance_num')
        else:
            result = queryset.values('college__name', 'teaching_time__title','total_studends_num', 'total_attendance_num')
        start=(page-1)*page_size
        data={'count':result.count(),'data':list(result[start:page*page_size])}
        return Response(data)

    def getRollSheet(self, request):

        page = request.query_params.get('page', 1)
        page_size = request.query_params.get('page_size', 5)
        page=int(page)
        page_size=int(page_size)
        if page_size > 20:
            page_size = 20
        id=request.query_params.get('id')
        start = (page - 1) * page_size
        if(id):
            result=RollCall.objects.filter(class_date__lte=timezone.now(),college_id=id).order_by('-state').values()
            data = {'count': result.count(), 'data': list(result[start:page * page_size])}
            return Response(data)
        result = RollCall.objects.filter(class_date__lte=timezone.now()).order_by('-state').values()
        data = {'count': result.count(), 'data': list(result[start:page * page_size])}
        return Response(data)

    def getStudentName(self, request):
        kangkename=request.query_params.get('kangkename')
        qingjianame = request.query_params.get('qingjianame')
        truant_name=[]
        leave_name=[]
        qj=qingjianame.split(",")
        kk = kangkename.split(",")
        for i in qj:
            result=Student.objects.filter(idcardnumber=i).values("name")
            for j in result:
                leave_name.append(j['name'])
        for i in kk:
            result=Student.objects.filter(idcardnumber=i).values("name")
            for j in result:
                truant_name.append(j['name'])
        data={
            "truant_name":truant_name,
            "leave_name":leave_name
        }
        return Response(data)





















